There are instances where we DO NOT want an hvm guest to run an
authorkaf24@firebug.cl.cam.ac.uk <kaf24@firebug.cl.cam.ac.uk>
Fri, 21 Apr 2006 08:56:50 +0000 (09:56 +0100)
committerkaf24@firebug.cl.cam.ac.uk <kaf24@firebug.cl.cam.ac.uk>
Fri, 21 Apr 2006 08:56:50 +0000 (09:56 +0100)
MP enabled kernel.  In such situations we should have a workaround to
guarantee hvm guests will not detect MP.

For example, in the absence of ACPI and MPS the installation code in some
linux distributions key off the presence of cpuid edx/HTT bit (indicating
the presence of Hyper-Threading Technology) to determine if another
logical processor is present and if so load an MP enabled kernel instead
of a uniprocessor kernel.  SMBIOS is also looked at for the same purpose
and presents a potential problem as well.  While both approaches for
selecting an MP kernel are debatable (since using MPS or ACPI have long
been the standard for MP detection), these approaches are something we
have to live and work around with because making a change in the fully
virtualized guest is not an option.

To solve the problem we need to hide all secondary processors from the hvm
guest.  Since the hvm does not surface MPS tables, we only need to deal
with ACPI, cpuid HTT, and possibly SMBIOS.   (I did not have time right
now to look closely at the hvm BIOS to know if SMBIOS is also going to be
a problem.)

Also fixes a logic problem the code path where apic=0 was not
being handled correctly (vmx path only).

Signed-off-by: Clyde Griffin <cgriffin@novell.com>
xen/arch/x86/hvm/svm/svm.c
xen/arch/x86/hvm/vmx/vmx.c

index ee7b8fcff247f66875270f6aa0974be7e7c8fb2b..dae853c968d05a0d4873522920acb1eb92e218d3 100644 (file)
@@ -931,7 +931,13 @@ static void svm_vmexit_do_cpuid(struct vmcb_struct *vmcb, unsigned long input,
     {
         if ( !hvm_apic_support(v->domain) ||
                 !vlapic_global_enabled((VLAPIC(v))) )
+        {
             clear_bit(X86_FEATURE_APIC, &edx);
+            /* Since the apic is disabled, avoid any confusion about SMP cpus being available */
+            clear_bit(X86_FEATURE_HT, &edx);  /* clear the hyperthread bit */
+            ebx &= 0xFF00FFFF;  /* set the logical processor count to 1 */
+            ebx |= 0x00010000;
+        }
            
 #if CONFIG_PAGING_LEVELS < 3
         clear_bit(X86_FEATURE_NX, &edx);
index 987015c5da0e85211654cb8105cba6698a70f429..052c11ba2adca7f56c6496ecff2eb14100af8bd9 100644 (file)
@@ -828,9 +828,16 @@ static void vmx_vmexit_do_cpuid(struct cpu_user_regs *regs)
 
     if ( input == 1 )
     {
-        if ( hvm_apic_support(v->domain) &&
+        if ( !hvm_apic_support(v->domain) ||
              !vlapic_global_enabled((VLAPIC(v))) )
+        {
             clear_bit(X86_FEATURE_APIC, &edx);
+            /* Since the apic is disabled, avoid any confusion about SMP cpus being available */
+            clear_bit(X86_FEATURE_HT, &edx);  /* clear the hyperthread bit */
+            ebx &= 0xFF00FFFF;  /* set the logical processor count to 1 */
+            ebx |= 0x00010000;
+        }
+
 
 #if CONFIG_PAGING_LEVELS < 3
         clear_bit(X86_FEATURE_PAE, &edx);